//
// 哈希表保存命令行
// Created by kenny on 25-11-4.
//
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "mcp_cmap.h"

// 哈希表大小
#define HASH_TABLE_SIZE 16

typedef struct HashNode {
    int key;               // 命令id
    CommandInfo value;     // 命令信息
    struct HashNode* next; // 解决哈希冲突
} HashNode;

typedef struct {
    HashNode* buckets[HASH_TABLE_SIZE];
} HashTable;

// 修改：使用指针并初始化为NULL
HashTable* cmd_table = NULL;

// 哈希函数
unsigned int hash(int key) {
    return key % HASH_TABLE_SIZE;
}

// 命令数据
const CommandInfo commands[] = {
    {1001, 0x01, "login"},
    {1002, 0x02, "Authorization"},
    {1003, 0x03, "Logout"},
    {1006, 0x06, "Heartbeat"},
    {1008, 0x08, "Query server time"},
    {1010, 0x10, "Positioning"},
    {1012, 0x12, "Alarm"},
    {1015, 0x15, "Device status"},
    {1018, 0x18, "Invite"},
    {1019, 0x19, "Bye"},
    {1022, 0x22, "Media list"},
    {1025, 0x25, "Media replay"},
    {1028, 0x28, "Media file upload"},
    {1031, 0x31, "Device control"},
    {1034, 0x34, "OTA upgrade"}
};

const int COMMAND_COUNT = sizeof(commands) / sizeof(commands[0]);

// 从哈希表查找数据
const CommandInfo* cmap_get(int key) {
    if (cmd_table == NULL) {
        return NULL;
    }

    unsigned int index = hash(key);
    HashNode* current = cmd_table->buckets[index];

    while (current != NULL) {
        if (current->key == key) {
            return &(current->value);
        }
        current = current->next;
    }
    return NULL;
}

// 插入数据到哈希表
void cmap_put(int key, const CommandInfo* value) {
    if (cmd_table == NULL) {
        return;
    }

    unsigned int index = hash(key);
    HashNode* node = (HashNode*)malloc(sizeof(HashNode));

    node->key = key;
    node->value = *value;
    node->next = cmd_table->buckets[index];
    cmd_table->buckets[index] = node;
}

/**
 * 初始化
 */
void cmap_init() {
    // 如果已经初始化，先释放
    if (cmd_table != NULL) {
        cmap_free();
    }

    // 分配哈希表内存
    cmd_table = (HashTable*)malloc(sizeof(HashTable));
    if (cmd_table == NULL) {
        return;
    }

    // 初始化桶
    for (int i = 0; i < HASH_TABLE_SIZE; i++) {
        cmd_table->buckets[i] = NULL;
    }

    // 数组压入 map
    for (int i = 0; i < COMMAND_COUNT; i++) {
        cmap_put(commands[i].id, &commands[i]);
    }
}

// 释放哈希表内存
void cmap_free() {
    if (cmd_table == NULL) {
        return;
    }

    for (int i = 0; i < HASH_TABLE_SIZE; i++) {
        HashNode* current = cmd_table->buckets[i];
        while (current != NULL) {
            HashNode* temp = current;
            current = current->next;
            free(temp);
        }
        cmd_table->buckets[i] = NULL;
    }

    // 重要：释放哈希表本身并将指针设为NULL
    free(cmd_table);
    cmd_table = NULL;
}